#include "robotmap.h"
#include "robot/robot.h"
#include <iostream>
#include <QtGui/QFileDialog>

#include "python2.7/Python.h"

RobotMap::RobotMap ( MapViewer* map, Robot* robot, int x, int y ) :
        _map ( map ), _robot ( robot )
{
     _coord.first = x ;
     _coord.second = y ;
    if ( _robot )
    {
        _robot->setRobotMap ( this ) ;
        updateRobotImagePosition() ;
    }
}

MapViewer* RobotMap::mapViewer() const
{
    return _map ;
}

Robot* RobotMap::robot() const
{
    return _robot ;
}

const Coord& RobotMap::position() const
{
    return _coord ;
}

void RobotMap::moveUp()
{
    _coord.second = _coord.second - 1 ;
    updateRobotImagePosition() ;
}

void RobotMap::moveDown()
{
    _coord.second = _coord.second+ 1 ;
    updateRobotImagePosition() ;
}

void RobotMap::moveLeft()
{
    _coord.first =  _coord.first - 1 ;
    updateRobotImagePosition() ;
}

void RobotMap::moveRight()
{
    _coord.first =  _coord.first  + 1 ;
    updateRobotImagePosition() ;
}

void RobotMap::updateRobotImagePosition()
{
    if (_robot && _map)
    {
        _robot->image()->setX ( _map->getPosition ( _coord.first, _coord.second ).first );
        _robot->image()->setY ( _map->getPosition ( _coord.first, _coord.second ).second );
    }
}

void RobotMap::setRobot ( Robot* robot )
{
    if ( _robot )
        delete _robot ;
    _robot = robot ;
    if ( _robot )
    {
        _robot->setRobotMap ( this ) ;
        updateRobotImagePosition() ;
    }
}

void RobotMap::setMapViewer ( MapViewer* mapviewer )
{
    if ( _map )
        delete _map ;
    _map = mapviewer ;
}

void RobotMap::addRessourceType ( const std::string& rt )
{
    _ressourcesTypes.push_back ( rt );
}

void RobotMap::setRessourceMatch(const QPixmap& tile, int rType)
{
    const Tile* t = 0 ;
    std::map<const Tile*, const QPixmap>::const_iterator it ;
    for (it = _map->ressources().begin() ; it != _map->ressources().end() ; it++)
    {
        if (it->second.toImage() == tile.toImage())
        {
            t = it->first ;
        }
    }
    if (t)
    {
        _ressourcesMatch.insert(std::pair<const Tile*, int>(t, rType)) ;
        std::cout << _ressourcesTypes.at(rType) << std::endl ;
    }
    else
    {
        std::cerr << "Unable to find correspondance between tiles" << std::endl ;
    }
}

int RobotMap::ressource(int x, int y) const
{
    const Tile* t = _map->ressourceAt(x, y) ;
    if (t)
        return _ressourcesMatch.at(t) ;
    else
        return -1 ;
}

const std::string& RobotMap::ressourceString(int x, int y) const
{
    if (x > 0 && x <= _map->map()->width() && y > 0 && y <= _map->map()->height())
    {
        const Tile* t = _map->ressourceAt(x, y) ;
        if (t)
            return _ressourcesTypes.at(_ressourcesMatch.at(t)) ;
        else
            return "" ;
    }
    else
    {
        std::cerr << "Bad location : " << x << " : " << y << std::endl ;
    }
}

std::list<int> RobotMap::ressources() const
{
    std::list<int> l ;
    return l ;
}

#include <python2.7/Python.h>
#include <boost/python.hpp>
#include <boost/python/copy_const_reference.hpp>
#include <boost/python/manage_new_object.hpp>

using namespace boost::python;
using namespace std ;

void RobotMap::launchScript(const std::string& file)
{
// 	std::cout << "Init...." << std::endl ;
// 	Py_Initialize();
// 	std::cout << "OK" << std::endl ;
//
// 	PyObject *pName = 0, *pModule = 0, *pDict = 0, *pFunc;
// 	PyObject *pArgs, *pValue;
//
// 	std::cout << "pName..." << std::endl ;
// 	pName = PyString_FromString(file.c_str());
// 	std::cout << "OK" << std::endl ;
// 	if(pName)
// 	/* Error checking of pName left out */
// 	if(!pName)
// 		std::cerr << "Not pName" << std::endl ;
// 	std::cout << "Module..." << std::endl ;
// 	pModule = PyImport_Import(pName);
// 	std::cout << "OK" << std::endl ;
// 	std::cout << "DECREF..." << std::endl ;
// 	Py_DECREF(pName);
// 	std::cout << "OK" << std::endl ;
//
// 	std::cout << "Moudle OK ? " << (pModule != 0) << std::endl ;
//
// 	if (pModule)
// 	{
// 		std::cout << "Oui pour le script Python" << std::endl ;
// 		Py_DECREF(pModule);
// 	}
// 	else
// 	{
// 		PyErr_Print();
// 	}
//
// 	std::cout << "DECREF ..." << std::endl ;
//
// 	std::cout << "OK" << std::endl ;
//
// 	Py_Finalize();

    Py_Initialize();
    object main_module(( handle<>(borrowed(PyImport_AddModule("__main__" )))));
    object main_namespace = main_module.attr("__dict__" );
    main_namespace["Robot"] = class_<Robot>("Robot", boost::python::init<std::string>())
                              .def("name", &Robot::name, boost::python::return_value_policy<boost::python::copy_const_reference>())
                              .def("sensorsCount", &Robot::sensorsCount)
                              .def("actuatorsCount", &Robot::actuatorsCount)

                              .def("sensorValue", &Robot::sensorValue)
                              .def("doActuatorAction", &Robot::doActuatorAction)

                              .def("moveUp", &Robot::moveUp)
                              .def("moveDown", &Robot::moveDown)
                              .def("moveLeft", &Robot::moveLeft)
                              .def("moveRight", &Robot::moveRight) ;

    QFile f ( QString(file.c_str()) ) ;
    if ( !f.open ( QIODevice::ReadOnly | QIODevice::Text ) )
    {
        std::cerr << "Unable to open " << file << std::endl ;
        return ;
    }

    main_namespace["a"] = ptr(_robot);

    QByteArray ba = f.readAll() ;
    if ( ba.data() != 0 )
    {
        PyRun_String( ba.data(), Py_file_input,
                      main_namespace.ptr(), main_namespace.ptr() );
    }

    //Agent = extract<Base&>(main_namespace["Agent"]); //Récup de l'instance agent du script dans l'objet C++
    //cout << "Agent: " << Agent.GetPoids() << endl;
    // Cleanup after Python...
    Py_Finalize();
}

void RobotMap::setRobotPosition(int x, int y)
{
	if(x > 0 && y > 0 && x <= _map->map()->width() && y <= _map->map()->height())
	{
		_coord.first = x ;
		_coord.second = y ;
		updateRobotImagePosition();
	}
}
